package com.v0710.esbconver.excel;

import cn.hutool.core.io.FileUtil;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.read.listener.ReadListener;
import com.v0710.esbconver.config.ConfigExcel;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Objects;

@Slf4j
@Data
public class ExcelReadListener extends WriteFile implements ReadListener<ExcelData> {

    boolean flagIn=false;
    boolean flagOut=false;
    boolean isArray=false;
    boolean reqIsArray=false;


    private ItemData reqItemDataArray;
    private ItemData itemDataArray;
    private HashMap<String,String> classDesc = new HashMap<>();


    private List<ItemData> inputList= new ArrayList<>();
    private List<ItemData> outList= new ArrayList<>();
    private List<String> tradeList= new ArrayList<>();

    private ConfigExcel configExcel;

    public ExcelReadListener(ConfigExcel configExcel) {
        this.configExcel = configExcel;
    }

    @Override
    public void invoke(ExcelData excelData, AnalysisContext analysisContext) {
        String sheetName = analysisContext.readSheetHolder().getSheetName();
        int sheetNo = analysisContext.readSheetHolder().getSheetNo();

        if(sheetNo < Integer.parseInt(configExcel.getSheetNo())){
            return;
        }

        if (!tradeList.isEmpty()){
            if(!tradeList.contains(sheetName)){
                return;
            }
        }

        if ("交易码".equals(excelData.getFlag())){
            classDesc.put("trandCode",excelData.getTrandCode());
            classDesc.put("sysName",excelData.getNameChinese());
            return;
        }

        if ("交易名称".equals(excelData.getFlag())){
            classDesc.put("scene",excelData.getNameChinese());
            return;
        }

        if("输入".equals(excelData.getFlag().trim())){
            flagIn=true;
            flagOut=false;
            return;
        }

        if("输出".equals(excelData.getFlag().trim())){
            flagIn=false;
            flagOut=true;
            return;
        }

        if(!excelData.getNameEnglish().isEmpty()){

            if(flagIn){
                if("Array".equals(excelData.getDataType().trim())
                        && "start".equals(excelData.getArryFlag().toLowerCase().trim())){
                    reqIsArray=true;

                    ItemData itemData = new ItemData();
                    itemData.setItemType(excelData.getDataType().trim());
                    itemData.setNameEnglish(excelData.getNameEnglish());
                    itemData.setNameChinese(excelData.getNameChinese().concat(excelData.getConstraint()));
                    itemData.setConstraint(excelData.getConstraint());
                    itemData.setNameDesc(excelData.getArryFlag());
                    itemData.setRequired(excelData.getRequired());
                    reqItemDataArray = itemData;
                }else if("Array".equals(excelData.getDataType().trim())
                        && "end".equals(excelData.getArryFlag().toLowerCase().trim())){
                    reqIsArray=false;
                    inputList.add(reqItemDataArray);
                    return;
                }
                if (reqIsArray && !excelData.getDataType().equals("Array")){
                    ItemData.ArrayItem arrayItem = new ItemData.ArrayItem();
                    arrayItem.setNameChinese(excelData.getNameChinese());
                    arrayItem.setNameEnglish(excelData.getNameEnglish());
                    arrayItem.setConstraint(excelData.getConstraint());
                    arrayItem.setNameDesc(excelData.getArryFlag());
                    arrayItem.setRequired(excelData.getRequired());
                    reqItemDataArray.getArrayItem().add(arrayItem);

                }else if(!excelData.getDataType().equals("Array")){
                    ItemData itemData = new ItemData();
                    itemData.setNameEnglish(excelData.getNameEnglish());
                    itemData.setNameChinese(excelData.getNameChinese());
                    itemData.setItemType(excelData.getDataType());
                    itemData.setConstraint(excelData.getConstraint());
                    itemData.setNameDesc(excelData.getArryFlag());
                    itemData.setRequired(excelData.getRequired());
                    inputList.add(itemData);
                }

            }

            if(flagOut){
                if("Array".equals(excelData.getDataType().trim())
                        && "start".equals(excelData.getArryFlag().toLowerCase().trim())){
                    isArray=true;

                    ItemData itemData = new ItemData();
                    itemData.setItemType(excelData.getDataType().trim());
                    itemData.setNameEnglish(excelData.getNameEnglish());
                    itemData.setNameChinese(excelData.getNameChinese().concat(excelData.getConstraint()));
                    itemData.setConstraint(excelData.getConstraint());
                    itemData.setNameDesc(excelData.getArryFlag());
                    itemData.setRequired(excelData.getRequired());
                    itemDataArray = itemData;
                }else if("Array".equals(excelData.getDataType().trim())
                        && "end".equals(excelData.getArryFlag().toLowerCase().trim())){
                    isArray=false;
                    outList.add(itemDataArray);
                    return;
                }

                if(isArray && !excelData.getDataType().equals("Array")){
                    ItemData.ArrayItem arrayItem = new ItemData.ArrayItem();
                    arrayItem.setNameChinese(excelData.getNameChinese());
                    arrayItem.setNameEnglish(excelData.getNameEnglish());
                    arrayItem.setConstraint(excelData.getConstraint());
                    arrayItem.setNameDesc(excelData.getArryFlag());
                    arrayItem.setRequired(excelData.getRequired());
                    itemDataArray.getArrayItem().add(arrayItem);
                }else if(!excelData.getDataType().equals("Array")){
                    ItemData itemData = new ItemData();
                    itemData.setItemType(excelData.getDataType().trim());
                    itemData.setNameEnglish(excelData.getNameEnglish());
                    itemData.setNameChinese(excelData.getNameChinese().concat(excelData.getConstraint()));
                    itemData.setConstraint(excelData.getConstraint());
                    itemData.setNameDesc(excelData.getArryFlag());
                    itemData.setRequired(excelData.getRequired());
                    outList.add(itemData);
                }
            }
        }
    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
        try{
            String sheetName = analysisContext.readSheetHolder().getSheetName();
            if(!tradeList.isEmpty()){
                if(!tradeList.contains(sheetName)){
                    return;
                }
            }

            flagOut=false;
            flagIn=false;

            String configPath = System.getProperty("user.dir") + "/src/main/resources/application.properties";
            System.err.println("配置文件路径："+configPath);
            List<String> properties = FileUtil.readLines(configPath, "UTF-8");
            String[] split = new String[0];
            for (String property : properties) {
                if (property.startsWith("yufan.wang.sheet.name")) {
                    String string = property.split("=")[1];
                     split = string.split(",");
                }
            }
            String javaname = "";
            for (String s : split) {
                if (s.contains(sheetName)) {
                    javaname=s.split(":")[1];
                }
            }

            if (Objects.equals(javaname, "")){
                throw new RuntimeException("文件名不存在请确认【yufan.wang.sheet.name】");
            }
            String reqFile=configExcel.getClassFilePath().concat("req/").concat(javaname).concat("Req.java");
            String rspFile=configExcel.getClassFilePath().concat("resp/").concat(javaname).concat("Resp.java");

            writeFile(reqFile,inputList);
            writeFile(rspFile,outList);
            inputList.clear();;
            outList.clear();
        }catch (Exception e){
            log.error(":",e);
            throw e;
        }
    }

    private boolean isContainsTrade(String trade){
        if(tradeList == null ){

        }
        return true;
    }

    @Override
    public void writeFile(String filePth, List<ItemData> itemDataList)  {
        File file = new File(filePth);
        log.info("写文件={}", filePth);
        if(file.isFile()){
            if("true".equals(configExcel.getFileOvrrideEnable())){
                file.delete();
            }else{
                throw new RuntimeException("文件已存在");
            }
        }

        String [] fileSplit = file.getName().split(".java");

        String crlf = System.getProperty("line.separator");
        try {
            FileWriter fileWriter = new FileWriter(filePth);
            if (file.getName().endsWith("Req.java")){
                fileWriter.write("package ".concat(configExcel.getClassPackage()).concat(";").concat(crlf).concat(crlf));
                fileWriter.write("import cn.swiftpass.transmit.core.ReqDto;"+crlf);
            }else {
                fileWriter.write("package ".concat(configExcel.getResponsePackage()).concat(";").concat(crlf).concat(crlf));
                fileWriter.write("import cn.swiftpass.transmit.core.RespDto;".concat(crlf));
            }
            fileWriter.write("import lombok.Data;".concat(crlf));
            fileWriter.write("import com.alibaba.fastjson.annotation.JSONField;".concat(crlf));

            fileWriter.write("import lombok.EqualsAndHashCode;".concat(crlf));
            fileWriter.write("import lombok.experimental.Accessors;".concat(crlf));
            fileWriter.write("import com.alibaba.fastjson.JSON;".concat(crlf));
            fileWriter.write("import com.alibaba.fastjson.serializer.SerializerFeature;".concat(crlf));
            fileWriter.write("import java.io.Serializable;".concat(crlf));
            fileWriter.write("import java.util.List;".concat(crlf).concat(crlf));

            fileWriter.write("/**".concat(crlf));
            fileWriter.write("秦农".concat(crlf));
            fileWriter.write("* "+classDesc.get("trandCode")+crlf);
            fileWriter.write("* "+classDesc.get("sysName")+crlf);
            fileWriter.write("* "+classDesc.get("scene")+crlf);
            fileWriter.write("*/"+crlf);
            fileWriter.write("@Data".concat(crlf));
            fileWriter.write("@EqualsAndHashCode(callSuper = true)"+crlf);
            fileWriter.write("@Accessors(chain = true)"+crlf);
            if (file.getName().endsWith("Req.java")){
                fileWriter.write("public class ".concat(fileSplit[0]).concat(" extends ReqDto<"+fileSplit[0]+"> ").concat("{").concat(crlf));
            }else {
                fileWriter.write("public class ".concat(fileSplit[0]).concat(" extends RespDto<"+fileSplit[0]+"> ").concat("{").concat(crlf));
            }


            itemDataList.forEach(one->{
                if("Array".equals(one.getItemType())){
                    try {
                        fileWriter.write("\t/**".concat(one.getNameChinese()+crlf)
                                .concat("* "+one.getRequired()+crlf)
                                .concat("* "+one.getConstraint()+crlf)
                                .concat("* "+one.getNameDesc()+crlf)
                                .concat("*/"+crlf));
                        fileWriter.write("\t\t@JSONField(name=\"".concat(one.getNameEnglish()).concat("\")").concat(crlf));
                        String lowerCase = one.getNameEnglish().substring(0, 1).toLowerCase();
                        String substring = one.getNameEnglish().substring(1);
                        fileWriter.write("\tprivate List<"
                                .concat(one.getNameEnglish().substring(0,1).toUpperCase())
                                .concat(one.getNameEnglish().substring(1))
                                .concat("> ")
                                .concat(lowerCase)
                                .concat(substring)
                                .concat(";".concat(crlf))
                        );

                        fileWriter.write("\t@Data".concat(crlf));
                        fileWriter.write("\t public static class "
                                .concat(one.getNameEnglish().substring(0,1).toUpperCase())
                                .concat(one.getNameEnglish().substring(1)).concat(" implements Serializable{").concat(crlf));

                        one.getArrayItem().forEach(itmeData->{
                            try {
                                fileWriter.write("\t\t/**".concat(crlf).concat(itmeData.getNameChinese().concat(crlf))
                                        .concat("* "+one.getRequired().concat(crlf))
                                        .concat("* "+one.getConstraint().concat(crlf))
                                        .concat("* "+one.getNameDesc().concat(crlf))
                                        .concat("*/").concat(crlf));
                                fileWriter.write("\t\t@JSONField(name=\"".concat(itmeData.getNameEnglish()).concat("\")").concat(crlf));
                                fileWriter.write("\t\tprivate String "
                                        .concat(itmeData.getNameEnglish().substring(0,1).toLowerCase())
                                        .concat(itmeData.getNameEnglish().substring(1))
                                        .concat(";").concat(crlf));
                            }catch (Exception e){
                               log.error(":",e);
                            }
                        });
                        fileWriter.write("\t}".concat(crlf));

                    } catch (IOException e) {
                        throw new RuntimeException(e);
                    }
                }else{
                    try {
                        fileWriter.write("\t/**".concat(crlf).concat(one.getNameChinese()).concat(crlf+one.getRequired()+crlf)
                                .concat(one.getConstraint()+"\n")
                                .concat(one.getNameDesc())
                                .concat("\n*/\n"));
                        fileWriter.write("\t@JSONField(name=\"".concat(one.getNameEnglish()).concat("\")".concat(crlf)));
                        fileWriter.write("\tprivate String "
                                .concat(one.getNameEnglish().substring(0,1).toLowerCase())
                                .concat(one.getNameEnglish().substring(1))
                                .concat(";").concat(crlf));
                    } catch (IOException e) {
                        throw new RuntimeException(e);
                    }

                }


            });
            if (file.getName().endsWith("Req.java")){
                fileWriter.write("@Override".concat(crlf));
                fileWriter.write("public String requestConvert("+fileSplit[0]+" request) {".concat(crlf));
                fileWriter.write("       return JSON.toJSONString(request, SerializerFeature.WriteMapNullValue);".concat(crlf));
                fileWriter.write("}".concat(crlf));
            }
            else {
                fileWriter.write("@Override\n");
                fileWriter.write("public "+fileSplit[0]+" responseConvert(String response) {\n");
                fileWriter.write("       return JSON.parseObject(response, "+fileSplit[0]+".class);\n");
                fileWriter.write("}\n");
            }

            fileWriter.write("}".concat(crlf));
            fileWriter.flush();
            fileWriter.close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

    }
}
